package org.ucas.faker.web.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.ucas.faker.web.entity.Depot;
import org.ucas.faker.web.entity.TaskLog;

import javax.transaction.Transactional;

@Service
@Transactional
public class LockService {

  @Autowired
  private TaskService taskService;

  @Autowired
  private DepotService depotService;

  public boolean tryLock(TaskLog task) {

    if(task == null || task.getDepotId() == null) return true;

    if(task.getVersion() == null) {
      Depot depot = depotService.load(task.getDepotId());
      if(depot == null) return false;
      task.setVersion(depot.getVersion());
    }

    TaskLog tmp = taskService.load(task.getDepotId(),task.getVersion(),task.getCategory());
    if(tmp != null) {
      task.setId(tmp.getId());
      TaskLog.TaskStatus status = tmp.getStatus();

      if(status.equals(TaskLog.TaskStatus.PROCESSING)) {
        return false;
      }
    }

    task.setStatus(TaskLog.TaskStatus.PROCESSING);

    taskService.persist(task);
    return true;
  }

  public void lock(TaskLog task) throws InterruptedException {
    while (!tryLock(task)) {
      Thread.sleep(3000);
    }
  }

  private TaskLog fetch(TaskLog task) {
    if(task.getId() != null)
      return task;
    if(task.getDepotId() == null || task.getVersion() ==null || task.getCategory() == null)
      return null;
    TaskLog tmp = taskService.load(task.getDepotId(),task.getVersion(),task.getCategory());
    if(tmp == null) return null;
    task.setId(tmp.getId());
    return task;
  }

  public void unlock(TaskLog task) {
    task = fetch(task);
    if(task != null) {
      task.setStatus(TaskLog.TaskStatus.FINISHED);
      taskService.persist(task);
    }
  }

  public void cancel(TaskLog task) {
    task = fetch(task);
    if(task != null) {
      task.setStatus(TaskLog.TaskStatus.CANCELED);
      taskService.persist(task);
    }
  }
}
